package com.wcity.manage.common.utils;

import com.wcity.manage.dao.model.Role;

import java.util.ArrayList;
import java.util.List;

/**
 * 鉴权工具
 *
 * @author dy
 * @modify jn
 */
public class AuthUtil {

    /**
     * 鉴权
     *
     * @param authId 权限识别id
     * @param role 角色
     * @return
     */
    public static boolean auth( int authId, Role role ) {

        if ( authId <= 0 ) return false;

        // 偏移值
        int i = authId % 63 == 0 ? 63 : authId % 63;

        // 判断属于哪个权限识别位
        int authNo = ( authId - i ) / 63 + 1;
        switch ( authNo ) {
            case 1:
                return check( i, role.getAuthA() );
            case 2:
                return check( i, role.getAuthB() );
            case 3:
                return check( i, role.getAuthC() );
            case 4:
                return check( i, role.getAuthD() );
            case 5:
                return check( i, role.getAuthE() );
            case 6:
                return check( i, role.getAuthF() );
            case 7:
                return check( i, role.getAuthG() );
            case 8:
                return check( i, role.getAuthH() );
        }
        return false;
    }

    /**
     * 授权
     *      最大授权authId范围为 1 ~ 504（ 8 * 63 ）
     *
     * @param authIds
     * @param role
     */
    public static void authorize( List<Integer> authIds, Role role ) {

        clear(role);

        for ( int authId : authIds ) {

            if ( authId <= 0 ) continue;

            // 偏移值
            int i = authId % 63 == 0 ? 63 : authId % 63;

            // 判断授权哪个权限识别位
            int authNo = ( authId - i ) / 63 + 1;
            switch ( authNo ) {
                case 1:
                    role.setAuthA( role.getAuthA() | (long) Math.pow( 2, i - 1 ) );
                    break;
                case 2:
                    role.setAuthB( role.getAuthB() | (long) Math.pow( 2, i - 1 ) );
                    break;
                case 3:
                    role.setAuthC( role.getAuthC() | (long) Math.pow( 2, i - 1 ) );
                    break;
                case 4:
                    role.setAuthD( role.getAuthD() | (long) Math.pow( 2, i - 1 ) );
                    break;
                case 5:
                    role.setAuthE( role.getAuthE() | (long) Math.pow( 2, i - 1 ) );
                    break;
                case 6:
                    role.setAuthF( role.getAuthF() | (long) Math.pow( 2, i - 1 ) );
                    break;
                case 7:
                    role.setAuthG( role.getAuthG() | (long) Math.pow( 2, i - 1 ) );
                    break;
                case 8:
                    role.setAuthH( role.getAuthH() | (long) Math.pow( 2, i - 1 ) );
                    break;
            }
        }
    }

    /**
     * 清除权限
     *
     * @param role
     * @return
     */
    public static void clear( Role role ) {
        role.setAuthA( 0 );
        role.setAuthB( 0 );
        role.setAuthC( 0 );
        role.setAuthD( 0 );
        role.setAuthE( 0 );
        role.setAuthF( 0 );
        role.setAuthG( 0 );
        role.setAuthH( 0 );
    }

    /**
     * 检查是否具有权限
     *
     * @param i
     * @param auth
     * @return
     */
    private static boolean check( int i, long auth ) {
        if ( i <=0 || i > 63 ) return false;
        long authNum = (long) Math.pow( 2, i - 1 );
        return ( authNum & auth ) == authNum;
    }

    /**
     * 获取角色所有授权authId
     *
     * @param role
     * @return
     */
    public static List<Integer> getAuthIds( Role role ) {
        List<Integer> authIds = new ArrayList<>();
        for( int i = 1; i <= AUTH_NUM * AUTH_LEN; i++ ) {
            if ( auth( i, role ) ) authIds.add( i );
        }
        return authIds;
    }

    /**
     * 权限识别位长度(二进制位数)
     */
    private static final int AUTH_LEN = 63;
    /**
     * 权限识别位数量
     */
    private static final int AUTH_NUM = 8;

}
